#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "esp_log.h"
#include "sd_spi.h"
#include <inttypes.h>
#include "driver/spi_common.h"

#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif

#define SD_SPI_HOST    SPI3_HOST
#define EXAMPLE_MAX_CHAR_SIZE 64

static const char *TAG = "example";

#define MOUNT_POINT "/sdcard"

#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
const char *names[] = {"CLK ", "MOSI", "MISO", "CS  "};
const int pins[] = {CONFIG_EXAMPLE_PIN_CLK,
                    CONFIG_EXAMPLE_PIN_MOSI,
                    CONFIG_EXAMPLE_PIN_MISO,
                    CONFIG_EXAMPLE_PIN_CS};

const int pin_count = sizeof(pins) / sizeof(pins[0]);
#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE
const int adc_channels[] = {CONFIG_EXAMPLE_ADC_PIN_CLK,
                            CONFIG_EXAMPLE_ADC_PIN_MOSI,
                            CONFIG_EXAMPLE_ADC_PIN_MISO,
                            CONFIG_EXAMPLE_ADC_PIN_CS};
#endif // CONFIG_EXAMPLE_ENABLE_ADC_FEATURE

pin_configuration_t config = {
    .names = names,
    .pins = pins,
#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE
    .adc_channels = adc_channels,
#endif
};
#endif // CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS

// Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu.
// You can also change the pin assignments here by changing the following 4 lines.
#define PIN_NUM_CS 45
#define PIN_NUM_MOSI 47
#define PIN_NUM_CLK 48
#define PIN_NUM_MISO 21

SD_Card_Info sdcardInfo;
sdmmc_host_t host_g;
sdspi_device_config_t slot_config_g;
sdmmc_card_t *card;

void list_directory_files(const char *directory_path) {
    DIR *dir;
    struct dirent *entry;

    // 打开目录
    dir = opendir(directory_path);
    if (dir == NULL) {
        perror("Failed to open directory");
        return;
    }

    // 遍历目录中的每个条目
    while ((entry = readdir(dir)) != NULL) {
        // 打印文件名
        printf("%s\n", entry->d_name);
    }

    // 关闭目录
    closedir(dir);
}

// 定义 write_string_to_file 函数
esp_err_t write_string_to_file(const char *filepath, const char *format, ...) {
    va_list args;
    char *buffer;
    size_t length;
    esp_err_t ret = ESP_OK;
    
    // 获取格式化后的字符串长度
    va_start(args, format);
    length = vsnprintf(NULL, 0, format, args);
    va_end(args);

    // 动态分配内存
    buffer = (char *)malloc(length + 1);
    if (buffer == NULL) {
        perror("Failed to allocate memory");
        return -1;
    }

    // 再次格式化字符串
    va_start(args, format);
    vsnprintf(buffer, length + 1, format, args);
    va_end(args);

    // 分段写入
    
    ESP_LOGI(TAG, "Opening file %s", filepath);
    FILE *f = fopen(filepath, "w");
    if (f == NULL)
    {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return ESP_FAIL;
    }
    for (size_t i = 0; i < length; i += EXAMPLE_MAX_CHAR_SIZE) {
        size_t chunk_size = (length - i > EXAMPLE_MAX_CHAR_SIZE) ? EXAMPLE_MAX_CHAR_SIZE : (length - i);
        char *chunk = (char *)malloc(chunk_size + 1);
        strncpy(chunk, buffer + i, chunk_size);
        chunk[chunk_size] = '\0';
        fprintf(f, chunk);
        // ret = s_example_write_file(filepath, chunk);
        free(chunk);
    }

    // 释放内存
    free(buffer);
    fclose(f);
    ESP_LOGI(TAG, "File written");
    ret = ESP_OK;
    return ret;
}

static esp_err_t s_example_write_file(const char *path, char *data)
{
    ESP_LOGI(TAG, "Opening file %s", path);
    FILE *f = fopen(path, "w");
    if (f == NULL)
    {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return ESP_FAIL;
    }
    fprintf(f, data);
    fclose(f);
    ESP_LOGI(TAG, "File written");

    return ESP_OK;
}

static esp_err_t s_example_read_file(const char *path)
{
    ESP_LOGI(TAG, "Reading file %s", path);
    FILE *f = fopen(path, "r");
    if (f == NULL)
    {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return ESP_FAIL;
    }
    // ESP_LOGE(TAG, "File %s size:%llu", path, f_size(f));
    char line[EXAMPLE_MAX_CHAR_SIZE];
    fgets(line, sizeof(line), f);
    fclose(f);

    // strip newline
    char *pos = strchr(line, '\n');
    if (pos)
    {
        *pos = '\0';
    }
    ESP_LOGI(TAG, "Read from file: '%s'", line);

    return ESP_OK;
}

/**
 * 读文件逐行读取  使用 __getline 函数
 */
void read_file_line_by_line(const char *filePath) {
    FILE *file = fopen(filePath, "r");
    if (file == NULL) {
        perror("Failed to open file");
        return;
    }

    char *line = NULL;
    size_t n = 0;
    ssize_t read;

    while ((read = __getline(&line, &n, file)) != -1) {
        // 去除末尾的换行符
        if (read > 0 && line[read - 1] == '\n') {
            line[read - 1] = '\0';
        }

        // 打印读取的每一行
        printf("%s\n", line);
    }

    free(line);
    fclose(file);
}

void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz)
{
    ESP_LOGI(TAG, "Using SPI peripheral");
    sdmmc_host_t host = SDSPI_HOST_DEFAULT();
    host.slot = SD_SPI_HOST;
    host.max_freq_khz = freq_khz;
    spi_bus_config_t bus_cfg = {
        .mosi_io_num = PIN_NUM_MOSI,
        .miso_io_num = PIN_NUM_MISO,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };
    esp_err_t ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return;
    }
    ESP_ERROR_CHECK(ret);

    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs = PIN_NUM_CS;
    slot_config.host_id = host.slot;
    *out_host = host;
    *out_slot_config = slot_config;
    
    const char mount_point[] = MOUNT_POINT;
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .format_if_mount_failed = true,
#else
        .format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files = 5,
        .allocation_unit_size = 16 * 1024};
    ESP_LOGI(TAG, "Mounting filesystem ...");
    ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                          "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
            ret = esp_vfs_fat_sdcard_format(mount_point, card);
            if (ret != ESP_OK) {
                ESP_LOGE(TAG, "format  failed!");
            } else {
                ESP_LOGI(TAG, "format  ok!");
                ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
                if (ret != ESP_OK) {
                    ESP_LOGE(TAG, "Mount sdcard failed again after format!");
                } else {
                    ESP_LOGI(TAG, "Mount sdcard ok after format!");
                }
            } 
        }
        else
        {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                          "Make sure SD card lines have pull-up resistors in place.",
                     esp_err_to_name(ret));
#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
            check_sd_card_pins(&config, pin_count);
#endif
        }
        return;
    }
    ESP_LOGI(TAG, "Filesystem mounted");
}

esp_err_t init_sd_card()
{
    init_sd_config(&host_g, &slot_config_g, SDMMC_FREQ_DEFAULT);
    esp_err_t ret = ESP_OK;
    card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
    if (card == NULL)
    {
        ESP_LOGE(TAG, "Failed to allocate sdmmc_card_t structure");
        ESP_ERROR_CHECK(ESP_ERR_NO_MEM);
    }

    ESP_LOGI(TAG, "-------------------------sdspi_host_init_device");
    int card_handle = -1;
    ret = sdspi_host_init_device((const sdspi_device_config_t *)&slot_config_g, &card_handle);
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "-------------------------sdmmc_card_init");
    ret = sdmmc_card_init(&host_g, card);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to initialize SD card (%s)", esp_err_to_name(ret));
        ESP_LOGE(TAG, "If you were using SDMMC and switched to SPI reinsert the SD card or power cycle the board");
        free(card);
        // ESP_ERROR_CHECK(ret);
    } else {
        ESP_LOGI(TAG, "SD card mounted - raw access");
        sdmmc_card_print_info(stdout, card);

        // *out_card = card;
        uint32_t total_kb = 0;
        uint32_t free_kb = 0;
        if (exf_getfree(&total_kb, &free_kb) == 0) {
            char sizeFree[64];
            // snprintf(sizeFree, sizeof(sizeFree), "%luMB", free_kb / 1024);
            // snprintf(disp_buf,sizeof(disp_buf),"%.1f", temp);
            // lv_label_set_text(s_sd_total_size_label, sizeFree);
            ESP_LOGI(TAG, "free_mb = %luMB", (uint32_t)(free_kb / 1024));
        } 
    }
    return ret;
}

void deinit_sd_card(sdmmc_card_t **card)
{
// Unmount SD card
#ifdef CONFIG_EXAMPLE_USE_SDMMC
    sdmmc_host_deinit();
#else  // CONFIG_EXAMPLE_USE_SDMMC
    sdspi_host_deinit();
#endif // CONFIG_EXAMPLE_USE_SDSPI

    // Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
    sd_pwr_ctrl_handle_t pwr_ctrl_handle = (*card)->host.pwr_ctrl_handle;
    esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
        ESP_ERROR_CHECK(ret);
    }
    pwr_ctrl_handle = NULL;
#endif

    free(*card);
    *card = NULL;
}

/**
 * 使用16G SD卡警告： esp_littlefs: SD card is too big (sector=512, count=31116288; total=15931539456 bytes),
 * throttling to maximum possible 8388607 blocks
 *
 * 问题：
 * https://github.com/joltwallet/esp_littlefs/issues/173
 * LittleFS 之前声称可以部分支持最高 4GB 的文件系统，但在最新发布的 v2.9 版本中，
 * 这一支持已经被正式回退到 2GB。大于 2GB 的功能并没有经过充分测试。
 * 所以，如果我是你的话，我不会尝试使用大于 2GB 的分区与 LittleFS 一起工作。
 */
// void sd_spi_littlefs_test(void)
// {
//     init_sd_config(&host_g, &slot_config_g, SDMMC_FREQ_DEFAULT);
//     esp_err_t ret = ESP_OK;
//     sdmmc_card_t *card;
//     ESP_LOGI(TAG, "Mounting SD card - LittleFS");

//     ret = init_sd_card(&card);
//     if (ret != ESP_OK)
//     {
//         ESP_LOGE(TAG, "Failed to initialize SD card (%s)", esp_err_to_name(ret));
//     }
//     ESP_ERROR_CHECK(ret);

//     esp_vfs_littlefs_conf_t conf = {
//         .base_path = SD_BASE_PATH,
//         .sdcard = card,
//         .format_if_mount_failed = true,
//     };
//     ret = esp_vfs_littlefs_register(&conf);

//     if (ret == ESP_OK)
//     {
//         ESP_LOGI(TAG, "LittleFS mounted to %s", SD_BASE_PATH);
//     }
//     else
//     {
//         if (ret == ESP_FAIL)
//         {
//             ESP_LOGE(TAG, "Failed to mount or format filesystem");
//         }
//         else if (ret == ESP_ERR_NOT_FOUND)
//         {
//             ESP_LOGE(TAG, "Failed to find LittleFS partition");
//         }
//         else
//         {
//             ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
//         }
//     }
//     ESP_LOGI(TAG, "SD card mounted - LittleFS");

//     // Unmount SD card
//     esp_vfs_littlefs_unregister_sdmmc(card);
//     deinit_sd_card(&card);
//     ESP_LOGI(TAG, "SD card unmounted - LittleFS");
// }

// 得到磁盘剩余容量
// drv:磁盘编号("0:"/"1:")
// total:总容量     （单位KB）
// free:剩余容量     （单位KB）
// 返回值:0,正常.其他,错误代码
uint8_t exf_getfree(uint32_t *total, uint32_t *free)
{
    if (!card) {
        return 1;  // 未初始化
    }
    FATFS *fs1;
    uint8_t res;
    DWORD fre_clust = 0, fre_sect = 0, tot_sect = 0;
    // 得到磁盘信息及空闲簇数量
    res = f_getfree(MOUNT_POINT, &fre_clust, &fs1);
    if (res == 0)
    {
        tot_sect = (fs1->n_fatent - 2) * fs1->csize; // 得到总扇区数
        fre_sect = fre_clust * fs1->csize;           // 得到空闲扇区数
#if _MAX_SS != 512                                   // 扇区大小不是512字节,则转换为512字节
        tot_sect *= fs1->ssize / 512;
        fre_sect *= fs1->ssize / 512;
#endif
        *total = tot_sect >> 1; // 单位为KB
        *free = fre_sect >> 1;  // 单位为KB
    }
    return res;
}


void sd_spi_test(void)
{
    esp_err_t ret;

    // Options for mounting the filesystem.
    // If format_if_mount_failed is set to true, SD card will be partitioned and
    // formatted in case when mounting fails.
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .format_if_mount_failed = true,
#else
        .format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files = 5,
        .allocation_unit_size = 16 * 1024};
    sdmmc_card_t *card;
    const char mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");

    // Use settings defined above to initialize SD card and mount FAT filesystem.
    // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
    // Please check its source code and implement error recovery when developing
    // production applications.
    ESP_LOGI(TAG, "Using SPI peripheral");

    // By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
    // For setting a specific frequency, use host.max_freq_khz (range 400kHz - 20MHz for SDSPI)
    // Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
    sdmmc_host_t host = SDSPI_HOST_DEFAULT();

    // For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
    // When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
    // and the internal LDO power supply, we need to initialize the power supply first.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
    sd_pwr_ctrl_ldo_config_t ldo_config = {
        .ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
    };
    sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;

    ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
        return;
    }
    host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif

    spi_bus_config_t bus_cfg = {
        .mosi_io_num = PIN_NUM_MOSI,
        .miso_io_num = PIN_NUM_MISO,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };

    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return;
    }

    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs = PIN_NUM_CS;
    slot_config.host_id = host.slot;

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                          "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
        }
        else
        {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                          "Make sure SD card lines have pull-up resistors in place.",
                     esp_err_to_name(ret));
#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
            check_sd_card_pins(&config, pin_count);
#endif
        }
        return;
    }
    ESP_LOGI(TAG, "Filesystem mounted");

    ESP_LOGI(TAG, "get_sdcard_size_info-----------------------");
    u_int32_t total_kb = 0;
    u_int32_t free_kb = 0;
    
    uint8_t res = exf_getfree(&total_kb, &free_kb);
    sdcardInfo.freeSize = "0 MB";
    if (res == 0) {
        char sizeFree[64];
        snprintf(sizeFree, sizeof(sizeFree), "%lluMB", ((uint64_t)free_kb) / 1024);
        ESP_LOGI(TAG, "Total space: %lu KB", total_kb);
        ESP_LOGI(TAG, "Free space: %lu KB", free_kb);
        sdcardInfo.freeSize = strdup(sizeFree);
        ESP_LOGI(TAG, "Free space: %llu MB", ((uint64_t)free_kb) / 1024);
    } else {
        ESP_LOGE(TAG, "Failed to get free space.");
    }
    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
    sdcardInfo.name = strdup(card->cid.name);
    const char *type;
    char speed[64];
    if (card->is_sdio)
    {
        type = "SDIO";
    }
    else if (card->is_mmc)
    {
        type = "MMC";
    }
    else
    {
        type = (card->ocr & (1 << 30)) ? "SDHC/SDXC" : "SDSC";
    }
    sdcardInfo.type = strdup(type);
    if (card->real_freq_khz == 0)
    {
        snprintf(speed, sizeof(speed), "Speed: N/A");
        // fprintf(stream, "Speed: N/A\n");
    }
    else
    {
        const char *freq_unit = card->real_freq_khz < 1000 ? "kHz" : "MHz";
        const float freq = card->real_freq_khz < 1000 ? card->real_freq_khz : card->real_freq_khz / 1000.0;
        const char *max_freq_unit = card->max_freq_khz < 1000 ? "kHz" : "MHz";
        const float max_freq = card->max_freq_khz < 1000 ? card->max_freq_khz : card->max_freq_khz / 1000.0;
        // fprintf(stream, "Speed: %.2f %s (limit: %.2f %s)%s\n", freq, freq_unit, max_freq, max_freq_unit, card->is_ddr ? ", DDR" : "");
        snprintf(speed, sizeof(speed), "%.2f %s", freq, freq_unit);
    }
    sdcardInfo.speed = strdup(speed);

    char size[64];
    snprintf(size, sizeof(speed), "%lluMB", ((uint64_t)card->csd.capacity) * card->csd.sector_size / (1024 * 1024));
    sdcardInfo.size = strdup(size);

    // Use POSIX and C standard library functions to work with files.
    // 列出目录中的所有条目
    list_directory_files(MOUNT_POINT);
    // First create a file.
    const char *file_hello = MOUNT_POINT "/hello.txt";
    char data[EXAMPLE_MAX_CHAR_SIZE];
    snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", card->cid.name);
    ret = s_example_write_file(file_hello, data);
    if (ret != ESP_OK)
    {
        return;
    }

    const char *file_foo = MOUNT_POINT "/foo.txt";

    // Check if destination file exists before renaming
    struct stat st;
    if (stat(file_foo, &st) == 0)
    {
        // Delete it if it exists
        unlink(file_foo);
    }

    // Rename original file
    ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
    if (rename(file_hello, file_foo) != 0)
    {
        ESP_LOGE(TAG, "Rename failed");
        return;
    }

    ret = s_example_read_file(file_foo);
    if (stat(file_foo, &st) == 0)
    {
        ESP_LOGI(TAG, "File %s exists ...", file_foo);
        ESP_LOGI(TAG, "File size: %ld bytes\n", st.st_size);
    }
    if (ret != ESP_OK)
    {
        return;
    }

    // Format FATFS
#ifdef CONFIG_EXAMPLE_FORMAT_SD_CARD
    ret = esp_vfs_fat_sdcard_format(mount_point, card);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to format FATFS (%s)", esp_err_to_name(ret));
        return;
    }

    if (stat(file_foo, &st) == 0)
    {
        ESP_LOGI(TAG, "file still exists");
        return;
    }
    else
    {
        ESP_LOGI(TAG, "file doesn't exist, formatting done");
    }
#endif // CONFIG_EXAMPLE_FORMAT_SD_CARD

    const char *file_nihao = MOUNT_POINT "/你好.txt";
    memset(data, 0, EXAMPLE_MAX_CHAR_SIZE);
    snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\nABCDEFGHIJKLMNOPQRSWUVWXYZ\nabcdefghijklmnopqrst", "Nihao", card->cid.name);
    ret = s_example_write_file(file_nihao, data);
    
    struct stat stNihao;
    if (stat(file_nihao, &stNihao) == 0)
    {
        ESP_LOGI(TAG, "File %s exists ...", file_nihao);
        ESP_LOGI(TAG, "File size write: %ld bytes\n", stNihao.st_size);
    }
    if (ret != ESP_OK)
    {
        return;
    }

    write_string_to_file(file_nihao, "%s %sret = s_example_write_file(file_nihao, data);\nformat123434934854935634395etyertwe8ryrieuytierghighidghisghisdhgidhgidhfshgfidhgisdhgdhgkhdg\nhdkghdkghkdhgdhgkdhgkdjghkdfjghkdfghkdjhg", "Nihao", "");
    read_file_line_by_line(file_nihao);
    if (stat(file_nihao, &stNihao) == 0)
    {
        ESP_LOGI(TAG, "File %s exists ...", file_nihao);
        ESP_LOGI(TAG, "File size after write: %ld bytes\n", stNihao.st_size);
    }
    // Open file for reading
    ret = s_example_read_file(file_nihao);
    if (ret != ESP_OK)
    {
        return;
    }

    // All done, unmount partition and disable SPI peripheral
    esp_vfs_fat_sdcard_unmount(mount_point, card);
    ESP_LOGI(TAG, "Card unmounted");

    // deinitialize the bus after all devices are removed
    spi_bus_free(host.slot);

    // Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
    ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
        return;
    }
#endif
}

SD_Card_Info getSdcardInfo(void)
{
    return sdcardInfo;
}